package com.ac.scum.log.task.face.config;

import com.ac.scum.config.bean.ServerFTPFileConfigAdmin;
import com.ac.scum.log.bean.Server;
import com.ac.scum.log.bean.ServerFTP;
import com.ac.scum.log.task.mapper.config.ServerFTPFileConfigAdminMapper;
import com.ac.scum.log.task.mapper.server.ServerFTPMapper;
import com.ac.scum.log.task.service.ServerService;
import com.ac.scum.log.task.utils.ftp.FTPUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@AllArgsConstructor
public class AdminFTPSyncTask {
    private final ServerService serverService;
    private final RedissonClient redissonClient;
    private final ServerFTPMapper serverFTPMapper;
    private final ServerFTPFileConfigAdminMapper serverFTPFileConfigAdminMapper;
    private final static String GodModeStr = "[godmode]";

    private static final ThreadPoolTaskExecutor threadPool;

    static {
        threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(20);
        threadPool.setMaxPoolSize(40);
        threadPool.setQueueCapacity(Integer.MAX_VALUE);
        threadPool.setKeepAliveSeconds(60);
        threadPool.setThreadNamePrefix("config-update-consumer-");
        threadPool.setWaitForTasksToCompleteOnShutdown(true);
        threadPool.initialize();
    }

    @Scheduled(cron = "0/2 * * * * ?")
    @Transactional
    public void syncStart() {
        List<Server> servers = serverService.getServersWithSpecifiedPackageIds(1L);
        if (!servers.isEmpty()) {
            for (Server server : servers) {
                threadPool.submit(() -> {
                    RLock lock = redissonClient.getLock("server-config-update-server-lock-" + server.getId().toString());
                    if (lock.isLocked()) {
                        return;
                    }
                    try {
                        lock.lock(5, TimeUnit.MINUTES);
                        sync(server);
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    } finally {
                        lock.unlock();

                    }
                });
            }
        } else {
            log.info("暂无任务");
        }
    }

    public void sync(Server server) throws JSchException, IOException, SftpException {
        List<ServerFTPFileConfigAdmin> needUpdateConfigs = serverFTPFileConfigAdminMapper.selectList(Wrappers.lambdaQuery(ServerFTPFileConfigAdmin.class).eq(ServerFTPFileConfigAdmin::getServerId, server.getId()));
        ServerFTP serverFTP = serverFTPMapper.selectOne(Wrappers.lambdaQuery(ServerFTP.class).eq(ServerFTP::getServerId, server.getId()));
        if (serverFTP == null) {
            return;
        }
        StringBuilder needUploadConfigStr = new StringBuilder();
        int delRow = 0;
        int normalRow = 0;
        int addRow = 0;
        for (ServerFTPFileConfigAdmin config : needUpdateConfigs) {
            boolean isSkip = false;
            if (config.getExpirationTime() != null) {
                isSkip = LocalDateTime.now().isAfter(config.getExpirationTime());
            }
            isSkip = isSkip || config.getType() == 4;
            if (isSkip) {
                delRow++;
                config.setSavedFlag(false);
                continue;
            }
            if (config.getSavedFlag()) {
                normalRow++;
            } else {
                addRow++;
            }
            needUploadConfigStr.append(config.getSteamId())
                    .append(config.getGodModelFlag() ? GodModeStr : Strings.EMPTY)
                    .append("\r");
            config.setSavedFlag(true);
        }

        int countRow = delRow + addRow;
        if (countRow > 0) {
            String adminConfigPath = serverFTP.getConfigPath() + File.separator + "AdminUsers.ini";
            byte[] byteArray = needUploadConfigStr.toString().getBytes(StandardCharsets.UTF_8);
            FTPUtil ftpUtil = new FTPUtil(serverFTP);
            ftpUtil.connect();
            ftpUtil.uploadFile(new ByteArrayInputStream(byteArray), adminConfigPath);
            List<Long> needDeleteIds = needUpdateConfigs.stream().filter(config -> !config.getSavedFlag()).map(ServerFTPFileConfigAdmin::getId).toList();
            if (!needDeleteIds.isEmpty()) {
                serverFTPFileConfigAdminMapper.deleteBatchIds(needDeleteIds);
            }
            needUpdateConfigs.stream().filter(ServerFTPFileConfigAdmin::getSavedFlag).forEach(serverFTPFileConfigAdminMapper::updateById);
            ftpUtil.disconnect();
            log.info("======config======>>>{} admin config updated del:{}row add:{}row normal:{}", server.getName(), delRow, addRow, normalRow);
        }
    }
}
